home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / tcop / dest.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  7.2 KB  |  364 lines

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *    dest.c
  4.  *    
  5.  *   DESCRIPTION
  6.  *    support for various communication destinations - see lib/H/tcop/dest.h
  7.  *
  8.  *   INTERFACE ROUTINES
  9.  *     BeginCommand - prepare destination for tuples of the given type
  10.  *     EndCommand - tell destination that no more tuples will arrive
  11.  *     NullCommand - tell dest that the last of a query sequence was processed
  12.  *    
  13.  *   NOTES
  14.  *    These routines do the appropriate work before and after
  15.  *    tuples are returned by a query to keep the backend and the
  16.  *    "destination" portals synchronized.
  17.  *
  18.  *   IDENTIFICATION
  19.  *    $Header: /private/postgres/src/tcop/RCS/dest.c,v 1.14 1992/05/06 06:02:28 mer Exp $
  20.  * ----------------------------------------------------------------
  21.  */
  22.  
  23. #include "tmp/postgres.h"
  24.  
  25. RcsId("$Header: /private/postgres/src/tcop/RCS/dest.c,v 1.14 1992/05/06 06:02:28 mer Exp $");
  26.  
  27. #include "parser/parse.h"
  28. #include "access/htup.h"
  29. #include "tmp/simplelists.h"
  30. #include "tmp/libpq-be.h"
  31. #include "access/printtup.h"
  32. #include "tmp/portal.h"
  33. #include "utils/log.h"
  34.  
  35. #include "nodes/pg_lisp.h"
  36. #include "tcop/dest.h"
  37.  
  38. #include "catalog/pg_type.h"
  39. #include "utils/mcxt.h"
  40.  
  41. /* ----------------
  42.  *    output functions
  43.  * ----------------
  44.  */
  45. void
  46. donothing(tuple, attrdesc)
  47.     List tuple;
  48.     List attrdesc;
  49. {
  50. }
  51.  
  52. void
  53. (*DestToFunction(dest))()
  54.     CommandDest    dest;
  55. {
  56.     switch (dest) {
  57.     case RemoteInternal:
  58.     return printtup_internal;
  59.     break;
  60.  
  61.     case Remote:
  62.     return printtup;
  63.     break;
  64.     
  65.     case Local:
  66.     return be_printtup;
  67.     break;
  68.     
  69.     case Debug:
  70.     return debugtup;
  71.     break;
  72.     
  73.     case None:
  74.     default:
  75.     return donothing;
  76.     break;
  77.     }    
  78.  
  79.     /*
  80.      * never gets here, but DECstation lint appears to be stupid...
  81.      */
  82.  
  83.     return donothing;
  84. }
  85.  
  86. #define IS_APPEND_TAG(tag) (*tag == 'A' && *(tag+1) == 'P')
  87.  
  88. /* ----------------
  89.  *     EndCommand - tell destination that no more tuples will arrive
  90.  * ----------------
  91.  */
  92. void
  93. EndCommand(commandTag, dest)
  94.     String      commandTag;
  95.     CommandDest    dest;
  96. {
  97.     char buf[64];
  98.  
  99.     switch (dest) {
  100.     case RemoteInternal:
  101.     case Remote:
  102.     /* ----------------
  103.      *    tell the fe that the query is over
  104.      * ----------------
  105.      */
  106.     pq_putnchar("C", 1);
  107.     pq_putint(0, 4);
  108.     if (IS_APPEND_TAG(commandTag))
  109.     {
  110.         sprintf(buf, "%s %d", commandTag, GetAppendOid());
  111.         pq_putstr(buf);
  112.     }
  113.     else
  114.         pq_putstr(commandTag);
  115.     pq_flush();
  116.     break;
  117.  
  118.     case Local:
  119.     case Debug:
  120.     break;
  121.     case CopyEnd:
  122.     pq_putnchar("Z", 1);
  123.     pq_flush();
  124.     break;
  125.     case None:
  126.     default:
  127.     break;
  128.     }
  129. }
  130.  
  131. /*
  132.  * These are necessary to sync communications between fe/be processes doing
  133.  * COPY rel TO stdout
  134.  * 
  135.  * or 
  136.  *
  137.  * COPY rel FROM stdin
  138.  *
  139.  */
  140.  
  141. void
  142. SendCopyBegin()
  143. {
  144.     pq_putnchar("B", 1);
  145.     pq_putint(0, 4);
  146.     pq_flush();
  147. }
  148.  
  149. void
  150. ReceiveCopyBegin()
  151. {
  152.     pq_putnchar("D", 1);
  153.     pq_putint(0, 4);
  154.     pq_flush();
  155. }
  156.  
  157. /* ----------------
  158.  *     NullCommand - tell dest that the last of a query sequence was processed
  159.  * 
  160.  *     Necessary to implement the hacky FE/BE interface to handle
  161.  *    multiple-return queries.
  162.  * ----------------
  163.  */
  164. void
  165. NullCommand(dest)
  166.     CommandDest    dest;
  167. {
  168.     switch (dest) {
  169.     case RemoteInternal:
  170.     case Remote: {
  171.     /* Do any asynchronous notification.  If front end wants to poll,
  172.        it can send null queries to call this function.
  173.        */
  174.     PQNotifyList *nPtr;
  175.     extern GlobalMemory notifyContext;
  176.     MemoryContext orig;
  177.  
  178.     if (notifyContext == NULL) {
  179.         notifyContext = CreateGlobalMemory("notify");
  180.     }
  181.     orig = MemoryContextSwitchTo((MemoryContext)notifyContext);
  182.  
  183.     for (nPtr = PQnotifies() ;
  184.          nPtr != NULL;
  185.          nPtr = (PQNotifyList *)SLGetSucc(&nPtr->Node)) {
  186.         pq_putnchar("A",1);
  187.         pq_putint(0, 4);
  188.         pq_putstr(nPtr->relname);
  189.         pq_putint(nPtr->be_pid,4);
  190.         PQremoveNotify(nPtr);
  191.     }
  192.     pq_flush();
  193.     PQcleanNotify();    /* garbage collect */
  194.     (void) MemoryContextSwitchTo(orig);
  195.  
  196.     /* ----------------
  197.      *    tell the fe that the last of the queries has finished
  198.      * ----------------
  199.      */
  200.     pq_putnchar("I", 1);
  201.     pq_putint(0, 4);
  202.     pq_flush();
  203.     }
  204.     break;
  205.  
  206.     case Local:
  207.     case Debug:
  208.     case None:
  209.     default:
  210.     break;
  211.     }    
  212. }
  213.  
  214. /* ----------------
  215.  *     BeginCommand - prepare destination for tuples of the given type
  216.  * ----------------
  217.  */
  218. void
  219. BeginCommand(pname, operation, attinfo, isIntoRel, isIntoPortal, tag, dest)
  220.     char     *pname;
  221.     int        operation;
  222.     LispValue     attinfo;
  223.     bool    isIntoRel;
  224.     bool    isIntoPortal;
  225.     char    *tag;
  226.     CommandDest    dest;
  227. {
  228.     PortalEntry    *entry;
  229.     struct attribute **attrs;
  230.     int    natts;
  231.     int    i;
  232.     char   *p;
  233.     
  234.     natts = CInteger(CAR(attinfo));
  235.     attrs  = (struct attribute **) CADR(attinfo);
  236.  
  237.     switch (dest) {
  238.     case RemoteInternal:
  239.     case Remote:
  240.     /* ----------------
  241.      *    if this is a "retrieve portal" query, just return
  242.      *    because nothing needs to be sent to the fe.
  243.      * ----------------
  244.      */
  245.         ResetAppendOid();
  246.     if (isIntoPortal)
  247.         return;
  248.         
  249.     /* ----------------
  250.      *    if portal name not specified for remote query,
  251.      *    use the "blank" portal.
  252.      * ----------------
  253.      */
  254.     if (pname == NULL)
  255.         pname = "blank";
  256.     
  257.     /* ----------------
  258.      *    send fe info on tuples we're about to send
  259.      * ----------------
  260.      */
  261.     pq_flush();
  262.     pq_putnchar("P", 1);    /* new portal.. */
  263.     pq_putint(0, 4);    /* xid */
  264.     pq_putstr(pname);    /* portal name */
  265.     
  266.     /* ----------------
  267.      *    if this is a retrieve, then we send back the tuple
  268.      *    descriptor of the tuples.  "retrieve into" is an
  269.      *    exception because no tuples are returned in that case.
  270.      * ----------------
  271.      */
  272.     if (operation == RETRIEVE && !isIntoRel) {
  273.         pq_putnchar("T", 1);    /* type info to follow.. */
  274.         pq_putint(natts, 2);    /* number of attributes in tuples */
  275.     
  276.         for (i = 0; i < natts; ++i) {
  277.         pq_putstr(attrs[i]->attname);    /* if 16 char name oops.. */
  278.         pq_putint((int) attrs[i]->atttypid, 4);
  279.         pq_putint(attrs[i]->attlen, 2);
  280.         }
  281.     }
  282.     pq_flush();
  283.     break;
  284.     
  285.     case Local:
  286.     /* ----------------
  287.      *    prepare local portal buffer for query results
  288.      *    and setup result for PQexec()
  289.      * ----------------
  290.      */
  291.     entry = be_currentportal();
  292.     if (pname != NULL)
  293.         pbuf_setportalinfo(entry, pname);
  294.     
  295.     if (operation == RETRIEVE && !isIntoRel) {
  296.         be_typeinit(entry, attrs, natts);
  297.         p = (char *) palloc(strlen(entry->name)+2);
  298.         p[0] = 'P';
  299.         strcpy(p+1,entry->name);
  300.     } else {
  301.         p = (char *) palloc(strlen(tag)+2);
  302.         p[0] = 'C';
  303.         strcpy(p+1,tag);
  304.     }
  305.     entry->result = p;
  306.     break;
  307.     
  308.     case Debug:
  309.     /* ----------------
  310.      *    show the return type of the tuples
  311.      * ----------------
  312.      */
  313.     if (pname == NULL)
  314.         pname = "blank";
  315.     
  316.     showatts(pname, natts, attrs);
  317.     break;
  318.     
  319.     case None:
  320.     default:
  321.     break;
  322.     }
  323. }
  324.  
  325. static ObjectId AppendOid;
  326.  
  327. void
  328. ResetAppendOid()
  329. {
  330.     AppendOid = InvalidObjectId;
  331. }
  332.  
  333. #define MULTI_TUPLE_APPEND -1
  334.  
  335. void
  336. UpdateAppendOid(newoid)
  337.     ObjectId newoid;
  338. {
  339.     /*
  340.      * First update after AppendOid was reset (at command beginning).
  341.      */
  342.     if (AppendOid == InvalidObjectId)
  343.     AppendOid = newoid;
  344.     /*
  345.      * Already detected a multiple tuple append, return a void oid ;)
  346.      */
  347.     else if (AppendOid == MULTI_TUPLE_APPEND)
  348.     return;
  349.     /*
  350.      * Oid has been assigned once before, tag this as a multiple tuple
  351.      * append.
  352.      */
  353.     else
  354.     AppendOid = MULTI_TUPLE_APPEND;
  355. }
  356.  
  357. ObjectId
  358. GetAppendOid()
  359. {
  360.     if (AppendOid == MULTI_TUPLE_APPEND)
  361.     return InvalidObjectId;
  362.     return AppendOid;
  363. }
  364.